/***********************************************************************
 ** Reykjavik University
 ** Grímur Tómasson & Eiríkur Torfason
 ** Copyright (c) 2011. All rights reserved.
 **********************************************************************/

#include "UtilityV2.h"

#include <limits.h>
#include <iostream>

//----------------------------------------------------------------------------------------------------------
//
// Constants for the values assigned for two and three in a row
//
const signed char TWO_IN_A_ROW_SCORE = 3;
const signed char THREE_IN_ROW_SCORE = 9;

// bitmask corresponds to board as follows in 7x6 case:
//  .  .  .  .  .  .  .  TOP
//  5 12 19 26 33 40 47
//  4 11 18 25 32 39 46
//  3 10 17 24 31 38 45
//  2  9 16 23 30 37 44
//  1  8 15 22 29 36 43
//  0  7 14 21 28 35 42  BOTTOM

int countSetBits (bitboard x) //Brian Kernighan's way
{
	int count = 0;
	//printDebug( x );
	while (x) 
	{
		count++;
		x &= x - 1; // reset LS1B
	}
	//std::cout << "count: " << count << std::endl;
	return count;
}

int twoInARowCount( const bitboard& board )
{
	return	countSetBits( board & (board>>H1) ) +
			countSetBits( board & (board>>1) ) +
			countSetBits( board & (board>>HEIGHT) ) +
			countSetBits( board & (board>>H2) );
}

int threeInARowCount( const bitboard& board )
{
	bitboard horizontal = board & (board>>H1);
	bitboard vertical = board & (board>>1); ;
	bitboard diagonal1 = board & (board>>HEIGHT);
	bitboard diagonal2 = board & (board>>H2);
	
	return	countSetBits( horizontal & (horizontal >> H1) ) +
			countSetBits( vertical & (vertical >> 1) ) +
			countSetBits( diagonal1 & (diagonal1 >> HEIGHT)) +
			countSetBits( diagonal2 & (diagonal2 >> 2*H2));
}


//----------------------------------------------------------------------------------------------------------
//This version only looks for three in a row, not two and not wether they can be extended, it's a test
int utilityV2( bitboard* bitboardArrayPointer[], int* currentPlyPointer, int side )
{
	//
	//Check for a win
	//
	if( hasWon( *bitboardArrayPointer[side] ) )
	{
		return side == 0 ? INT_MAX : INT_MIN;
	}
	
	int score = ( threeInARowCount( *bitboardArrayPointer[0] ) * THREE_IN_ROW_SCORE ) + (twoInARowCount( *bitboardArrayPointer[0] ) * TWO_IN_A_ROW_SCORE );
	score -= ( ( threeInARowCount( *bitboardArrayPointer[1] ) * THREE_IN_ROW_SCORE ) + (twoInARowCount( *bitboardArrayPointer[1] ) * TWO_IN_A_ROW_SCORE ) );
		
	if( side == 1 )
	{
		score = -score;
	}
	return score;	
}
//----------------------------------------------------------------------------------------------------------

